package com.jvm.memory.leak;

import java.util.HashSet;
import java.util.Set;
import java.util.Vector;

/**
 * 内存泄漏
 *
 * @author Lizhong
 * @date 2019/2/20
 */

public class MemoryLeak {

    static Vector v = new Vector(10);

    /**
     * 对象o不能回收
     */
    public void xxTest() {
        for (int i = 1; i < 100; i++) {
            Object o = new Object();
            v.add(o);
            o = null;
        }
    }

    /**
     * Person.class需重写hashCode
     * @param args
     * @throws InterruptedException
     *
     */
    public static void main(String[] args) throws InterruptedException {
        Set<Person> set = new HashSet<Person>();
        Person p1 = new Person("唐僧", "pwd1", 25);
        Person p2 = new Person("孙悟空", "pwd2", 26);
        Person p3 = new Person("猪八戒", "pwd3", 27);
        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println("总共有:" + set.size() + " 个元素!"); //结果：总共有:3 个元素!
        p3.setAge(2); //修改p3的年龄,此时p3元素对应的hashcode值发生改变
        set.remove(p3); //此时remove不掉，造成内存泄漏
        set.add(p3); //重新添加，居然添加成功
        System.out.println("总共有:" + set.size() + " 个元素!"); //结果：总共有:4 个元素!
        for (Person person : set) {
            System.out.println(person);
        }
    }
}

class A {
    public A() {
        B.getInstance().setA(this);
    }
// ....
}

/**
 *显然B采用singleton模式，它持有一个A对象的引用，而这个A类的对象将不能被回收。
 * 想象下如果A是个比较复杂的对象或者集合类型会发生什么情况
 */

//B类采用单例模式
class B {
    private A a;

    private static B instance = new B();

    public B() {
    }

    public static B getInstance() {
        return instance;
    }

    public void setA(A a) {
        this.a = a;
    }
//getter...

}

